package io.potato.ts.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import io.potato.core.CrudService;
import io.potato.core.util.Strings;
import io.potato.ts.common.Constants;
import io.potato.ts.domain.SmsStatusReport;
import io.potato.ts.repository.SmsStatusReportRepository;
import lombok.extern.slf4j.Slf4j;


/**
 * 短信状态报告服务类
 * 
 * @author timl
 *
 * <p>2019-01-07 15:13:58</p>
 */
@Service
@Transactional
@Slf4j
public class SmsStatusReportService extends CrudService<SmsStatusReport, Long> {

	@Autowired
	SmsStatusReportRepository repository;
	
	@Autowired
	SmsSendedRecordService sendedService;
	
	@Autowired
	SmsService smsService;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Override
	protected JpaRepository<SmsStatusReport, Long> getRepository() {
		return repository;
	}

	/**
	 * 接收云端发过来的短信报告
	 * @param smsReport  短信报告内容
	 */
	public void receive(SmsStatusReport smsReport) {
		
		if (needReport(smsReport)) {
			String msgId = smsService.getMsgId(smsReport.getHwMsgId());
			if (msgId == null) {
				for (int i = 0; i < 80; i++) {
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
					}
					msgId = smsService.getMsgId(smsReport.getHwMsgId());
					if (msgId != null) {
						log.warn("get msgid in " + i + " times");
						break;
					}
				}
			}
			smsReport.setMsgId(msgId);
		}
		
		if (needSaveStatusReport(smsReport)) {
			// 保存短信报告
			insert(smsReport);
		} 
		
		// 更新已发记录
		sendedService.updateReceiveStatus(smsReport);
	}
	
	/**
	 * 是否需要保存短信报告
	 * @param smsReport  短信报告
	 * @return  需要 true  不需要 false
	 */
	private boolean needSaveStatusReport(SmsStatusReport smsReport) {
		// 失败的，或者needReport = 1的 要保存到数据库
		return ( smsReport.getStatus().intValue() > 0
				|| (needReport(smsReport) && smsReport.getMsgId() != null)
				);
	}
	
	private boolean needReport(SmsStatusReport s) {
		return Constants.NeedReport.YES.equals(s.getNeedReport());
	}
	
	/**
	 * 根据短信ID查询未读的短信报告
	 * @param msgids  短信ID
	 * @return
	 */
	public List<SmsStatusReport> getStatusReport(String batchCode, List<String> msgids) {
		List<SmsStatusReport> list = this.repository.findByMsgIds(batchCode, msgids);
		return list;
	}
	
	/**
	 * 根据拓展码批量查询未读短信报告
	 * @param extendCode  拓展码
	 * @param count  返回记录数
	 * @return
	 */
	public List<SmsStatusReport> getStatusReport(String batchCode, Integer count) {
		if (count == null || count <= 0) {
			count = 10;
		}
		List<SmsStatusReport> list = this.repository.findByBatchCode(batchCode, count);
		return list;
	}
	
	/**
	 * 更新短信报告为已读， 已读的短信报告不会被查询到
	 * @param list  
	 */
	public void updateReadStatus(List<SmsStatusReport> list) {
		if (list == null || list.isEmpty()) {
			return;
		}
		
		List<Long> ids = new ArrayList<>();
		list.forEach(s -> ids.add(s.getId()));
		
		String sql = String.format("update sms_status_report set read_status =  1 where id in (%s)", Strings.join(ids, ','));
		int rows = jdbcTemplate.update(sql);
		log.debug("update " + rows + " rows");
	}
	
	/**
	 * 异步更新短信报告为已读， 已读的短信报告不会被查询到
	 * @param list  
	 */
	@Async
	public void updateReadStatusAsync(List<SmsStatusReport> list) {
		this.updateReadStatus(list);
	}
	
	/**
	 * 插入记录到数据库
	 * @param report  状态报告记录
	 */
	public void insert(SmsStatusReport r) {
		String sql = "INSERT INTO `sms_status_report` \n" + 
				"(`user_code`, `batch_code`, `extend_code`, `msg_id`, `hw_msg_id`, `total`, `status`, "
				+ "`status_desc`, `source`, `org_code`, `sender_type`, `dest_num`, `read_status`, `need_report`) \n" + 
				"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
		
		jdbcTemplate.update(sql, 
				r.getUserCode(), r.getBatchCode(), r.getExtendCode(), r.getMsgId(), r.getHwMsgId(), r.getTotal(), r.getStatus(), 
				r.getStatusDesc(), r.getSource(), r.getOrgCode(), r.getSenderType(), r.getDestNum(), r.getReadStatus(), r.getNeedReport());
	}
	
}
